const ci = require('miniprogram-ci');
const fs = require('fs').promises;
const fsSync = require('fs');
const path = require('path');

// 从环境变量获取配置
const STATUS_FILE = process.env.STATUS_FILE;
const PRIVATE_KEY_CONFIG = process.env.PRIVATE_KEY_CONFIG;
const RETRY_COUNT = 2; // 失败重试次数

// 状态管理：记录处理结果（成功/失败）
const StatusManager = {
  async read() {
    if (!fsSync.existsSync(STATUS_FILE)) {
      throw new Error(`状态文件不存在：${STATUS_FILE}`);
    }
    const data = await fs.readFile(STATUS_FILE, 'utf-8');
    return JSON.parse(data);
  },

  async recordResult(app, isSuccess, errorMsg = '') {
    const status = await this.read();
    status.processed.push({
      appid: app.appid,
      name: app.name,
      status: isSuccess ? 'success' : 'fail',
      error: isSuccess ? '' : errorMsg,
      time: new Date().toLocaleString()
    });
    status.lastUpdated = new Date().toLocaleString();
    await fs.writeFile(STATUS_FILE, JSON.stringify(status, null, 2));
  },

  async getNextApp() {
    const status = await this.read();
    const jsonData = await ConfigReader.read();
    const allApps = jsonData.appIds || [];

    // 如果配置中指定了isReverse为t，则倒序执行数组
    if (jsonData.isReverse === 't') {
      allApps.reverse();
    }

    // 筛选未处理的小程序（排除已记录在processed中的）
    const processedAppIds = status.processed.map(item => item.appid);
    return allApps.find(app => !processedAppIds.includes(app.appid));
  }
};

// 配置读取：获取版本、描述等
const ConfigReader = {
  // 缓存属性
  _cache: null,

  async read() {
    // 如果已有缓存，直接返回缓存数据
    if (this._cache) {
      return this._cache;
    }

    if (!fsSync.existsSync(PRIVATE_KEY_CONFIG)) {
      throw new Error(`配置文件不存在：${PRIVATE_KEY_CONFIG}`);
    }
    const data = await fs.readFile(PRIVATE_KEY_CONFIG, 'utf-8');
    // 读取后存入缓存
    this._cache = JSON.parse(data);
    return this._cache;
  },

  async getVersion(app) {
    const jsonData = await this.read();
    return app.version || jsonData.version || '1.0.0';
  },

  async getDescription(app) {
    const jsonData = await this.read();
    return app.desc || jsonData.desc || '自动上传';
  },

  // 新增方法：手动清除缓存（如需刷新配置时使用）
  clearCache() {
    this._cache = null;
  }
};

// 动态获取项目路径的方法
const getProjectRootPath = async () => {
  const config = await ConfigReader.read(); // 读取配置
  const buildModel = config.buildModel || 'HBuilderX'; // 默认 HBuilderX
  const env = config.env || 'build'; // 优先用配置中的 env
  return path.resolve(process.env.ROOT_DIR, buildModel === 'cli' ? `./dist/${env}/mp-weixin` : `./unpackage/dist/${env}/mp-weixin`);
};

// 项目配置：修改project.config.json
const ProjectConfig = {
  async set(app) {
    const projectRootPath = await getProjectRootPath();
    const configPath = path.join(projectRootPath, 'project.config.json');
    if (!fsSync.existsSync(configPath)) {
      throw new Error(`项目配置文件不存在：${configPath}`);
    }

    const data = await fs.readFile(configPath, 'utf-8');
    const json = JSON.parse(data);

    // 更新appid和项目名，确保setting字段存在
    json.appid = app.appid;
    json.projectname = app.name || `小程序_${app.appid}`;
    if (!json.setting) {
      json.setting = {
        es6: true,
        minifyJS: true,
        minifyWXML: true,
        minifyWXSS: true,
        minify: true
      };
    }

    await fs.writeFile(configPath, JSON.stringify(json, null, 4));
  }
};

// 上传逻辑：带重试机制
const Uploader = {
  async upload(app, retryLeft = RETRY_COUNT) {
    try {
      // 1. 设置项目配置
      await ProjectConfig.set(app);

      // 2. 验证私钥
      const privateKeyPath = path.resolve(process.env.ROOT_DIR, `./privateKey/private.${app.appid}.key`);
      if (!fsSync.existsSync(privateKeyPath)) {
        throw new Error(`私钥文件不存在：${privateKeyPath}`);
      }

      // 创建项目实例时，动态获取路径
      const projectRootPath = await getProjectRootPath();

      // 3. 创建项目实例
      const project = new ci.Project({
        appid: app.appid,
        type: 'miniProgram',
        projectPath: projectRootPath,
        privateKeyPath: privateKeyPath,
        ignores: [
          'node_modules/**/*',
          '*.log',
          '**/*.map',
          'test/**/*',
          'package.json',
          'README.md'
        ],
        cache: false // 禁用缓存，避免旧配置干扰
      });

      // 4. 执行上传
      await ci.upload({
        project,
        version: await ConfigReader.getVersion(app),
        desc: await ConfigReader.getDescription(app),
        setting: {
          es6: true,
          minifyJS: true,
          minifyWXML: true,
          minifyWXSS: true,
          minify: true
        },
        threads: 3,
        timeout: 8 * 60 * 1000, // 延长超时，应对大文件
        onProgressUpdate: (res) => {
          // console.log(res);
        }
      });

      return {success: true};
    } catch (err) {
      if (retryLeft > 0) {
        console.warn(`重试上传（剩余${retryLeft}次）：${err.message}`);
        return this.upload(app, retryLeft - 1); // 递归重试
      }
      // 重试耗尽，返回失败
      return {success: false, error: err.message};
    }
  }
};

// Worker主逻辑
const run = async () => {
  try {
    // 获取下一个待处理的小程序
    const app = await StatusManager.getNextApp();
    if (!app) {
      console.log('没有待处理的小程序');
      process.exit(0);
    }

    console.log(`\n开始处理：${app.name}（${app.appid}）`);
    const uploadResult = await Uploader.upload(app);

    // 记录结果并退出
    if (uploadResult.success) {
      await StatusManager.recordResult(app, true);
      console.log(`✅ 上传成功：${app.name}`);
      process.exit(0); // 成功退出码0
    } else {
      await StatusManager.recordResult(app, false, uploadResult.error);
      console.error(`❌ 上传失败：${app.name}（原因：${uploadResult.error}）`);
      process.exit(1); // 失败退出码1（主程序会忽略此错误继续）
    }
  } catch (err) {
    console.error('Worker执行异常：', err.message);
    process.exit(1);
  }
};

run();
